package org.xx.armory.commons;

import static org.apache.commons.lang3.StringUtils.leftPad;

/**
 * 表示两个字符串的比较结果。
 *
 * @author Haart
 */
@SuppressWarnings("ClassCanBeRecord")
public final class StringComparisonResult {
    /**
     * 不存在任何不同之处的比较结果
     */
    static final StringComparisonResult NONE = new StringComparisonResult(-1, 0, 0);
    private final int diffPos;
    private final int cp1;
    private final int cp2;

    /**
     * 表示两个字符串不相同之处的对象。
     *
     * @param diffPos
     *         不相同之处的下标，从{@code 0}开始。
     * @param cp1
     *         第一个字符串的字符。
     * @param cp2
     *         第二个字符串的字符。
     */
    private StringComparisonResult(
            int diffPos,
            int cp1,
            int cp2
    ) {
        this.diffPos = diffPos;
        this.cp1 = cp1;
        this.cp2 = cp2;
    }

    /**
     * 构造一个{@code StringComparisonResult}对象。
     *
     * @param diffPos
     *         不相同之处的下标，从{@code 0}开始。
     * @param cp1
     *         第一个字符串的字符。
     * @param cp2
     *         第二个字符串的字符。
     * @return 根据指定参数构造的{@code StringComparisonResult}对象。
     */
    public static StringComparisonResult of(
            int diffPos,
            int cp1,
            int cp2
    ) {
        return new StringComparisonResult(diffPos, cp1, cp2);
    }

    /**
     * 格式化代码点。
     *
     * @param cp
     *         待格式化的字符。
     * @return 格式化结果。如果参数{@code ch}是{@code null}则返回空字符串。
     */
    private static String formatCodePoint(
            int cp
    ) {
        if (cp >= 32 && cp < 127) {
            return "'" + (char) cp + "'";
        } else {
            return "\\u" + leftPad(Integer.toHexString(cp), 4, '0');
        }
    }

    /**
     * 是否不存在不同之处。
     *
     * @return 如果不存在不同之处则返回{@code true}，否则返回{@code false}。
     */
    public boolean isSame() {
        return this.diffPos < 0;
    }

    @Override
    public String toString() {
        if (this.diffPos < 0) {
            return "no difference";
        } else {
            return "difference at [" + diffPos + "]: " + formatCodePoint(cp1) + " != " + formatCodePoint(cp2);
        }
    }
}
